package com.liit.controller.weixin.process;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.web.subject.WebSubject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import cn.liit.weixin.core.basic.accesstoken.AccessTokenSupport;
import cn.liit.weixin.core.config.Config;
import cn.liit.weixin.message.model.req.ReqBaseMessage;
import cn.liit.weixin.message.model.req.ScanEventMessage;
import cn.liit.weixin.message.model.resp.RespBaseMessage;
import cn.liit.weixin.message.process.receive.ReceiveProcessor;
import cn.liit.weixin.templatemsg.utils.MsgUtil;
import cn.liit.weixin.userinfo.model.UserInfo;
import cn.liit.weixin.userinfo.utils.Util;

import com.liit.entity.OrgInfoFormMap;
import com.liit.entity.PartyAttendFormMap;
import com.liit.entity.PartyFormMap;
import com.liit.entity.PartySignFormMap;
import com.liit.entity.WeixinUserFormMap;
import com.liit.mapper.PartyMapper;
import com.liit.mapper.WeixinUserMapper;
import com.liit.spring.SpringUtils;
import com.liit.util.Common;
import com.liit.util.IntegralUtils;
import com.liit.util.PropertiesUtils;
import com.liit.util.RegionUtils;

/**
 * 
 * @author dingweibo
 * @Title: ScanMsgProcess.java
 * @Description: 扫码事件
 * @date 2016年2月15日
 */
public class ScanMsgProcess extends ReceiveProcessor {

	private static final Logger logger = LoggerFactory.getLogger(ScanMsgProcess.class);

	public ScanMsgProcess(String msgType, String event) {
		super(msgType, event);
	}

	@Override
	public RespBaseMessage doProcess(ReqBaseMessage reqBaseMessage) {
		RespBaseMessage respBaseMessage = null;
		try {

			String openid = reqBaseMessage.getFromUserName();
			UserInfo userInfo = Util.getUserInfo(AccessTokenSupport.getAccess_token(), openid);

			WeixinUserMapper mapper = SpringUtils.getBean(WeixinUserMapper.class);
			List<WeixinUserFormMap> wxUsers = mapper.findByAttribute("openid", openid, WeixinUserFormMap.class);
			if (CollectionUtils.isEmpty(wxUsers)) {
				// 添加微信用户
				WeixinUserFormMap weixinUser = new WeixinUserFormMap();
				weixinUser.put("openid", openid);
				weixinUser.put("nickname", Common.removeEmoji(userInfo.getNickname()));
				weixinUser.put("sex", userInfo.getSex());
				weixinUser.put("city", userInfo.getCity());
				weixinUser.put("province", userInfo.getProvince());
				weixinUser.put("headImgUrl", userInfo.getHeadimgurl());
				weixinUser.put("subscribeTime", new Timestamp(System.currentTimeMillis()));
				weixinUser.put("groupId", userInfo.getGroupid());
				mapper.addEntity(weixinUser);
			} else {
				// 更新微信用户信息
				WeixinUserFormMap weixinUser = wxUsers.get(0);
				weixinUser.put("nickname", Common.removeEmoji(userInfo.getNickname()));
				weixinUser.put("headImgUrl", userInfo.getHeadimgurl());
				weixinUser.put("groupId", userInfo.getGroupid());
				mapper.editEntity(weixinUser);
			}

			ScanEventMessage req = (ScanEventMessage) reqBaseMessage;
			scanEvent(openid, req.getEventKey());
		} catch (Exception e) {
			logger.error("微信扫码异常", e);
		}
		return respBaseMessage;
	}

	/**
	 * 带参数扫码事件
	 * 
	 * @param openid
	 * @param param
	 * @return
	 * @throws Exception
	 */
	public static int scanEvent(String openid, String param) throws Exception {

		// 已关注 带参数扫码
		if (StringUtils.isBlank(param)) {
			throw new NullPointerException("eventKey is null!");
		}

		PartyMapper mapper = SpringUtils.getBean(PartyMapper.class);

		// 活动信息
		PartyFormMap record = mapper.findbyFrist("id", param, PartyFormMap.class);

		// 机构信息
		OrgInfoFormMap orgInfo = mapper.findbyFrist("id", record.get("orgInfoId").toString(), OrgInfoFormMap.class);

		// 是否完善资料
		WeixinUserFormMap weixinUser = mapper.findbyFrist("openid", openid, WeixinUserFormMap.class);
		boolean isFinishInfo = StringUtils.isNotEmpty(weixinUser.getStr("name"));

		// 是否已报名活动
		PartySignFormMap partySign = new PartySignFormMap();
		partySign.put("partyId", param);
		partySign.put("openid", openid);
		boolean isSignParty = !CollectionUtils.isEmpty(mapper.findByNames(partySign));

		// 是否已参加活动
		PartyAttendFormMap partyAttend = new PartyAttendFormMap();
		partyAttend.put("partyId", param);
		partyAttend.put("openid", openid);
		List<PartyAttendFormMap> partyAttendList = mapper.findByNames(partyAttend);
		boolean isAttendParty = !CollectionUtils.isEmpty(partyAttendList);

		// 时间段
		Date startTime = record.getTimestamp("startTime");
		Date endTime = record.getTimestamp("endTime");
		boolean isA = false;// 活动开始前一小时之前
		boolean isB = false;// 活动开始前一小时
		boolean isC = false;// 活动开始与活动结束前20分钟之间
		boolean isD = false;// 活动结束前20分钟与活动结束之间
		boolean isE = false;// 活动结束之后
		if (System.currentTimeMillis() < DateUtils.addHours(startTime, -1).getTime()) {
			isA = true;
		} else if (System.currentTimeMillis() < startTime.getTime()) {
			isB = true;
		} else if (System.currentTimeMillis() < DateUtils.addMinutes(endTime, -20).getTime()) {
			isC = true;
		} else if (System.currentTimeMillis() < endTime.getTime()) {
			isD = true;
		} else if (System.currentTimeMillis() >= endTime.getTime()) {
			isE = true;
		}

		// 响应URL参数
		String respParam = "?partyId=" + param + "&type=" + (isA || !isSignParty ? 0 : (!isAttendParty ? 1 : 2));

		// 提示用户完善资料
		if (!isFinishInfo) {
			sendTemplateMsg(isA ? SIGN_ERROR : ATTEND_ERROR, openid, getAuthUrl("/weixin/user/editMyinfo.shtml" + respParam), "如需报名活动，请完善个人信息!", "未完善资料", record, weixinUser);
			return Common.PARTY_MSG_TYPE_USERINFO;
		}

		if (record.getInt("status") == Common.PARTY_STATUS_PASS || record.getInt("status") == Common.PARTY_STATUS_BEGIN) {

			if (isA) {
				if (isSignParty) {
					sendTemplateMsg(SIGN_ERROR, openid, "", "活动报名失败,原因:您已报名活动!", "重复报名活动", record, weixinUser);
					return Common.PARTY_MSG_TYPE_SIGNED;
				} else {
					mapper.addEntity(partySign);// 报名成功
					sendTemplateMsg(SIGN_SUCCESS, openid, getAuthUrl("/weixin/user/party/detail.shtml" + respParam), RegionUtils.getRegionNameById(orgInfo.getStr("area"))
							+ "社会组织公共活动服务平台——绿色伙伴欢迎您\\n\\n活动报名成功。(" + orgInfo.getStr("orgName") + ")感谢您的热情参与!", "", record, weixinUser);
					return Common.PARTY_MSG_TYPE_SIGN_SUCCESS;
				}
			}

			if (isB || isC) {
				if (isAttendParty) {
					sendTemplateMsg(ATTEND_ERROR, openid, "", "活动签到失败,原因:您已签到活动!", "", record, weixinUser);
					return Common.PARTY_MSG_TYPE_ATTENDED;
				} else {
					mapper.addEntity(partyAttend);// 签到活动
					IntegralUtils.getInstance().partyCheckin(openid, record.getInt("id"));// 添加签到积分
					sendTemplateMsg(ATTEND_SUCCESS, openid, getAuthUrl("/weixin/user/party/detail.shtml" + respParam), RegionUtils.getRegionNameById(orgInfo.getStr("area"))
							+ "社会组织公共活动服务平台——绿色伙伴欢迎您\\n\\n活动签到成功。(" + orgInfo.getStr("orgName") + ")感谢您的热情参与!", "", record, weixinUser);
					return Common.PARTY_MSG_TYPE_ATTEND_SUCCESS;
				}
			}

		}

		// D,E段时间
		if (isD || isE) {

			if (isAttendParty && partyAttendList.get(0).getInt("status") == 0) {
				// 用户已签到 未评价
				sendTemplateMsg(ATTEND_SUCCESS, openid, getAuthUrl("/weixin/user/party/comment.shtml" + respParam), "感谢您参与本次活动,评价活动可以获得积分哦!", "", record, weixinUser);
				return Common.PARTY_MSG_TYPE_COMMENT;
			} else if (isD && isAttendParty) {
				// 用户已签到 已评价
				sendTemplateMsg(ATTEND_SUCCESS, openid, "", "活动即将结束,感谢您的热情参与!", "", record, weixinUser);
				return Common.PARTY_MSG_TYPE_COMMENTED;
			} else if (isD) {
				if (isSignParty) {
					// 已报名 未签到
					sendTemplateMsg(ATTEND_ERROR, openid, "", "对不起,活动签到已结束!", "", record, weixinUser);
					return Common.PARTY_MSG_TYPE_ATTEND_FINISH;
				} else {
					// 未报名
					sendTemplateMsg(SIGN_ERROR, openid, "", "对不起,活动报名已结束!", "活动已结束", record, weixinUser);
					return Common.PARTY_MSG_TYPE_SIGN_FINISH;
				}
			} else {
				// 活动结束
				sendTemplateMsg(ATTEND_ERROR, openid, "", "活动已结束,感谢您的关注!", "", record, weixinUser);
				return Common.PARTY_MSG_TYPE_FINISH;
			}
		}
		return -1;
	}

	/**
	 * 获取授权URL
	 * 
	 * @param url
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private static String getAuthUrl(String url) throws UnsupportedEncodingException {
		HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils.getSubject()).getServletRequest();
		return String.format(PropertiesUtils.findPropertiesKey("auth.url"), Config.appid, URLEncoder.encode(Config.notifyurl + request.getContextPath() + url, "UTF-8"));
	}

	/**
	 * 发送活动模板消息
	 * 
	 * @param tType
	 * @param openid
	 * @param url
	 * @param first
	 * @param party
	 * @param weixinUser
	 */
	private static void sendTemplateMsg(int tType, String openid, String url, String first, String reason, PartyFormMap party, WeixinUserFormMap weixinUser) {
		String[] keywords = null;
		String templateId = null;

		// 消息参数
		String subject = party.getStr("subject");
		String startTime = Common.format(party.getTimestamp("startTime"), "yyyy-MM-dd HH:mm");
		String address = RegionUtils.getRegionNameById(party.getStr("area")) + " " + RegionUtils.getRegionNameById(party.getStr("street")) + " " + party.getStr("address");
		String contact = party.getStr("contact");
		String phone = party.getStr("phone");
		String name = weixinUser.getStr("name");

		switch (tType) {
		case SIGN_SUCCESS:
			keywords = new String[] { subject, startTime, address, "    " + contact, phone };
			templateId = PropertiesUtils.findPropertiesKey("templateid.sign.success");
			break;
		case SIGN_ERROR:
			keywords = new String[] { name, subject, startTime, address, reason };
			templateId = PropertiesUtils.findPropertiesKey("templateid.sign.error");
			break;
		case ATTEND_SUCCESS:
			keywords = new String[] { name, subject, Common.format(new Date(), "yyyy-MM-dd HH:mm"), address };
			templateId = PropertiesUtils.findPropertiesKey("templateid.attend.success");
			break;
		case ATTEND_ERROR:
			keywords = new String[] { name, subject, Common.format(new Date(), "yyyy-MM-dd HH:mm"), address };
			templateId = PropertiesUtils.findPropertiesKey("templateid.attend.error");
			break;
		default:
			logger.error("模板类型错误");
			return;
		}
		MsgUtil.sendTemplateMsg(AccessTokenSupport.getAccess_token(), openid, url, templateId, first + "\\n", keywords, "");
	}

	private static final int SIGN_SUCCESS = 0;// 报名成功
	private static final int SIGN_ERROR = 1;// 报名失败
	private static final int ATTEND_SUCCESS = 2;// 签到成功
	private static final int ATTEND_ERROR = 3;// 签到失败
}
